package ge.telasi.tasks.report;

import ge.telasi.tasks.LocaleManager;
import ge.telasi.tasks.controller.TaskController;
import ge.telasi.tasks.model.Task;
import ge.telasi.tasks.model.TaskBody;
import ge.telasi.tasks.model.TaskReceiver;
import ge.telasi.tasks.model.User;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;

/**
 * Task report.
 *
 * @author dimitri
 */
public class TaskReport extends Report {
    private String report;
    private long taskId;

    public TaskReport(long taskId) {
        this.taskId = taskId;
    }

    @Override
    public String getReport(EntityManager em) throws Exception {
        generateReport(em);
        return report;
    }

    public void generateReport(EntityManager em) throws IOException {
        Task task = new TaskController().findTask(em, taskId);
        Map<String, String> props = FileReader.getDefaultProperties();
        props.put("number", FileReader.squaredString(task.getNumber()));
        props.put("creation_date", FileReader.dateString(task.getCreated()));
        props.put("owner", encode(task.getOwner().getFullName()));
        props.put("status", encode(getStatusName(task.getTaskStatus())));
        props.put("subject", encode(task.getSubject()));
        String receivers[] = getReceivers(task);
        props.put("assignees", receivers[0]);
        props.put("carbon_copies", receivers[1]);
        props.put("priority", encode(getPriorityName(task)));
        if (task.getDueDate() == null) {
            props.put("due_date", "(განუსაზღვრელი)");
        } else {
            props.put("due_date", String.format("%1$td/%1$tm/%1$tY", task.getDueDate()));
        }
        StringBuilder bodies = new StringBuilder();
        for (TaskBody body : task.getBodies()) {
            bodies.append(getBody(body));
        }
        props.put("bodies", bodies.toString());
        report = FileReader.readFile("task.xml", props);
    }

    private void addUserToList(List<User> users, User user) {
        if (!users.contains(user)) {
            users.add(user);
        }
    }

    /**
     * Get receivers.
     */
    private String[] getReceivers(Task task) throws IOException {
        // get list of assignees and carbon copies
        List<User> lassignees = new ArrayList<User>();
        List<User> lcopies = new ArrayList<User>();
        for (TaskReceiver receiver : task.getReceivers()) {
            if (receiver.getUser() != null) { // as user
                if (!receiver.isCopy()) {
                    addUserToList(lassignees, receiver.getUser());
                } else {
                    addUserToList(lcopies, receiver.getUser());
                }
            } else { // as group
                for (User user : receiver.getGroup().getUsers()) {
                    if (!receiver.isCopy()) {
                        addUserToList(lassignees, user);
                    } else {
                        addUserToList(lcopies, user);
                    }
                }
            }
        }

        // build assignees string
        StringBuilder assignees = new StringBuilder();
        boolean first = true;
        for (User user : lassignees) {
            if (!first) {
                assignees.append(", ");
            }
            assignees.append(encode(user.getFullName()));
            first = false;
        }

        // build copies string
        StringBuilder carbonCopies = new StringBuilder();
        first = true;
        for (User user : lcopies) {
            if (!first) {
                carbonCopies.append(", ");
            }
            carbonCopies.append(encode(user.getFullName()));
            first = false;
        }
        if (first) {
            carbonCopies.append(" -- ");
        }

        return new String[]{assignees.toString(), carbonCopies.toString()};
    }

    /**
     * Get task body.
     */
    private String getBody(TaskBody body) throws IOException {
        Map<String, String> props = FileReader.getDefaultProperties();
        props.put("author", userToString(body.getOwner()));
        props.put("date", encode(body.getCreated().getTime().toString()));
        props.put("status", getStatusName(body.getTaskStatus()));
        String[] bodies = body.getBody().split("[\n\r]");
        StringBuilder b = new StringBuilder();
        for (String bodyElement : bodies) {
            b.append(MessageFormat.format(
                    "<fo:block font-family=\"{0}\" font-size=\"{1}\" padding-bottom=\"10pt\">",
                    props.get("def-font-name"), props.get("def-font-size")));
            b.append(encode(bodyElement));
            b.append("</fo:block>");
        }
        props.put("body", b.toString());
        return FileReader.readFile("task_body.xml", props);
    }

    public String getStatusName(int status) {
        return Task.getStatusName(lm, status);
    }

    public String getPriorityName(Task task) {
        switch (task.getPriority()) {
            case Task.PRIORITY_NORMAL:
                return lm.getMessage("Task.Priority.Normal");
            case Task.PRIORITY_HIGH:
                return lm.getMessage("Task.Priority.High");
            case Task.PRIORITY_LOW:
                return lm.getMessage("Task.Priority.Low");
            default:
                return "?";
        }
    }

}
